package org.cloudbus.cloudsim.provisioners;

import org.cloudbus.cloudsim.Vm;

public abstract class DiskProvisioner {

    /** The total bandwidth capacity from the host that the provisioner can allocate to VMs. */
    private long disk;

    /** The available bandwidth. */
    private long availableDisk;

    /**
     * Creates the new BwProvisioner.
     *
     * @param disk The total bandwidth capacity from the host that the provisioner can allocate to VMs.
     *
     * @pre disk >= 0
     * @post $none
     */
    public DiskProvisioner(long disk) {
        setDisk(disk);
        setAvailableDisk(disk);
    }

    /**
     * Allocates BW for a given VM.
     *
     * @param vm the virtual machine for which the bw are being allocated
     * @param disk the bw to be allocated to the VM
     *
     * @return $true if the bw could be allocated; $false otherwise
     *
     * @pre $none
     * @post $none
     */
    public abstract boolean allocateDiskForVm(Vm vm, long disk);

    /**
     * Gets the allocated BW for VM.
     *
     * @param vm the VM
     *
     * @return the allocated BW for vm
     */
    public abstract long getAllocatedDiskForVm(Vm vm);

    /**
     * Releases BW used by a VM.
     *
     * @param vm the vm
     *
     * @pre $none
     * @post none
     */
    public abstract void deallocateDiskForVm(Vm vm);

    /**
     * Releases BW used by all VMs.
     *
     * @pre $none
     * @post none
     */
    public void deallocateDiskForAllVms() {
        setAvailableDisk(getDisk());
    }

    /**
     * Checks if it is possible to change the current allocated BW for the VM
     * to a new amount, depending on the available BW.
     *
     * @param vm the vm to check if there is enough available BW on the host to
     * change the VM allocated BW
     * @param disk the new total amount of BW for the VM.
     *
     * @return true, if is suitable for vm
     */
    public abstract boolean isSuitableForVm(Vm vm, long disk);

    /**
     * Gets the bw capacity.
     *
     * @return the bw capacity
     */
    public long getDisk() {
        return disk;
    }

    /**
     * Sets the bw capacity.
     *
     * @param disk the new bw capacity
     */
    protected void setDisk(long disk) {
        this.disk = disk;
    }

    /**
     * Gets the available BW in the host.
     *
     * @return available bw
     *
     * @pre $none
     * @post $none
     */
    public long getAvailableDisk() {
        return availableDisk;
    }

    /**
     * Gets the amount of used BW in the host.
     *
     * @return used bw
     *
     * @pre $none
     * @post $none
     */
    public long getUsedDisk() {
        return disk - availableDisk;
    }

    /**
     * Sets the available bw.
     *
     * @param availableDisk the new available bw
     */
    protected void setAvailableDisk(long availableDisk) {
        this.availableDisk = availableDisk;
    }


}
